package com.example.smartwaterapi.common.api;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 统一REST响应处理
 * 确保所有控制器返回的响应都被包装为RestApiResponse格式
 */
@RestControllerAdvice(basePackages = "com.example.smartwaterapi.controller")
public class RestControllerResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 如果返回类型已经是RestApiResponse，则不需要再次包装
        return !returnType.getParameterType().equals(RestApiResponse.class);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        // 如果返回值为null，包装为无内容成功响应
        if (body == null) {
            return RestApiResponse.noContent();
        }

        // 如果已经是RestApiResponse类型，则直接返回
        if (body instanceof RestApiResponse) {
            return body;
        }

        // 对String类型特殊处理，避免类型转换异常
        if (body instanceof String) {
            // 这里需要单独处理String，因为Spring MVC使用StringHttpMessageConverter来处理String类型的返回值，
            // 它不会转换为JSON格式，所以在这里我们需要手动处理String类型的返回值
            // 在实际项目中，可以考虑引入统一的字符串返回约定，或者让String类型的返回值遵循不被包装的约定
            return body;
        }

        // 包装为成功响应
        return RestApiResponse.ok(body);
    }
} 